#ifndef __WIN_DLL_HOLDER_H__
#define __WIN_DLL_HOLDER_H__

#include <string>

#ifndef _WIN32_WINNT
#define _WIN32_WINNT 0x0501
#endif

#include <windows.h>

#include "../non_copyable.h"
#include "../exceptions.h"


namespace Boss
{

  BOSS_DECLARE_RUNTIME_EXCEPTION(DllHolder)

  namespace Internal
  {

    class DllHolder
      : private NonCopyable
    {
    public:
      DllHolder(const std::string &path)
        : DllInst(0)
      {
        if ((DllInst = LoadLibraryA(path.c_str())) == 0)
          throw DllHolderException("Can't load dll");
      }
      ~DllHolder()
      {
        FreeLibrary(DllInst);
      }

      template <typename T>
      T GetProc(const std::string &procName)
      {
        FARPROC Proc = GetProcAddress(DllInst, procName.c_str());
        if (!Proc)
          throw DllHolderException("Function not found");
        return reinterpret_cast<T>(Proc);
      }

    private:
      HINSTANCE DllInst;
    };

  }

  typedef Internal::DllHolder DllHolder;

}

#endif  // !__WIN_DLL_HOLDER_H__
